<template>
  <div class="tree-node" :class="dragClasses">
    <div 
      class="node-content" 
      :class="{ 
        'selected': selectedId === document.id, 
        'has-children': hasChildren,
        'drag-over': isDragOver,
        'dragging': isDragging
      }"
      :data-drop-position="dragOverPosition"
      :draggable="true"
      @click="onSelect"
      @dragstart="onDragStart"
      @dragend="onDragEnd"
      @dragover="onDragOver"
      @dragleave="onDragLeave"
      @drop="onDrop"
    >
      <div class="node-left">
        <button 
          v-if="hasChildren"
          @click.stop="toggleExpanded"
          class="expand-btn"
          :class="{ 'expanded': isExpanded }"
        >
          ▶
        </button>
        <span v-else class="expand-placeholder"></span>
        <span class="node-title">{{ document.name }}</span>
      </div>
      
      <div class="node-actions">
        <button @click.stop="onEdit" class="action-btn edit-btn" title="编辑">
          ✏️
        </button>
        <button @click.stop="onDelete" class="action-btn delete-btn" title="删除">
          🗑️
        </button>
      </div>
    </div>
    
    <div v-if="hasChildren && isExpanded" class="children">
      <DocumentTreeNode
        v-for="child in document.children"
        :key="child.id"
        :document="child"
        :selected-id="selectedId"
        @select="onChildSelect"
        @edit="onChildEdit"
        @delete="onChildDelete"
        @move="onChildMove"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import type { Document } from '../types/document'

interface Props {
  document: Document
  selectedId: number | null
}

const props = defineProps<Props>()

const emit = defineEmits<{
  select: [document: Document]
  edit: [document: Document]
  delete: [id: number]
  move: [{ sourceId: number; targetId: number | null; insertPosition: 'before' | 'after' | 'inside' }]
}>()

const isExpanded = ref(true) // 默认展开
const isDragging = ref(false)
const isDragOver = ref(false)
const dragOverPosition = ref<'before' | 'after' | 'inside'>('inside')

const hasChildren = computed(() => 
  props.document.children && props.document.children.length > 0
)

const dragClasses = computed(() => ({
  'drag-source': isDragging.value,
  'drag-target': isDragOver.value
}))

const toggleExpanded = () => {
  isExpanded.value = !isExpanded.value
}

const onSelect = () => {
  emit('select', props.document)
}

const onEdit = () => {
  emit('edit', props.document)
}

const onDelete = () => {
  emit('delete', props.document.id)
}

const onChildSelect = (document: Document) => {
  emit('select', document)
}

const onChildEdit = (document: Document) => {
  emit('edit', document)
}

const onChildDelete = (id: number) => {
  emit('delete', id)
}

const onChildMove = (moveData: { sourceId: number; targetId: number | null; insertPosition: 'before' | 'after' | 'inside' }) => {
  emit('move', moveData)
}

// 拖拽相关方法
const onDragStart = (event: DragEvent) => {
  if (!event.dataTransfer) return
  
  isDragging.value = true
  event.dataTransfer.effectAllowed = 'move'
  event.dataTransfer.setData('text/plain', JSON.stringify({
    id: props.document.id,
    name: props.document.name
  }))
  
  // 设置拖拽图像
  const dragImage = document.createElement('div')
  dragImage.textContent = `📄 ${props.document.name}`
  dragImage.style.cssText = `
    position: absolute;
    top: -1000px;
    padding: 8px 12px;
    background: #42b883;
    color: white;
    border-radius: 4px;
    font-size: 12px;
    white-space: nowrap;
  `
  document.body.appendChild(dragImage)
  event.dataTransfer.setDragImage(dragImage, 0, 0)
  
  setTimeout(() => {
    document.body.removeChild(dragImage)
  }, 0)
}

const onDragEnd = (event: DragEvent) => {
  isDragging.value = false
  isDragOver.value = false
}

const onDragOver = (event: DragEvent) => {
  event.preventDefault()
  if (!event.dataTransfer) return
  
  // 检查是否是有效的拖拽操作
  const dragData = event.dataTransfer.getData('text/plain')
  if (!dragData) return
  
  try {
    const sourceData = JSON.parse(dragData)
    if (sourceData.id === props.document.id) return // 不能拖到自己身上
    
    isDragOver.value = true
    event.dataTransfer.dropEffect = 'move'
    
    // 根据鼠标位置确定插入位置
    const rect = (event.currentTarget as HTMLElement).getBoundingClientRect()
    const y = event.clientY - rect.top
    const height = rect.height
    
    if (y < height * 0.25) {
      dragOverPosition.value = 'before'
    } else if (y > height * 0.75) {
      dragOverPosition.value = 'after'
    } else {
      dragOverPosition.value = 'inside'
    }
  } catch (e) {
    // 无效的拖拽数据
    event.dataTransfer.dropEffect = 'none'
  }
}

const onDragLeave = (event: DragEvent) => {
  // 只有当鼠标真正离开元素时才取消高亮
  const rect = (event.currentTarget as HTMLElement).getBoundingClientRect()
  const x = event.clientX
  const y = event.clientY
  
  if (x < rect.left || x > rect.right || y < rect.top || y > rect.bottom) {
    isDragOver.value = false
  }
}

const onDrop = (event: DragEvent) => {
  event.preventDefault()
  isDragOver.value = false
  
  if (!event.dataTransfer) return
  
  const dragData = event.dataTransfer.getData('text/plain')
  if (!dragData) return
  
  try {
    const sourceData = JSON.parse(dragData)
    if (sourceData.id === props.document.id) return // 不能拖到自己身上
    
    // 检查是否会造成循环引用
    if (wouldCreateCircularReference(sourceData.id, props.document.id)) {
      return // 静默失败，避免循环引用
    }
    
    // 确定目标ID
    let targetId: number | null = null
    if (dragOverPosition.value === 'inside') {
      targetId = props.document.id // 成为当前节点的子节点
    } else {
      targetId = props.document.parentId // 与当前节点同级
    }
    
    emit('move', {
      sourceId: sourceData.id,
      targetId: targetId,
      insertPosition: dragOverPosition.value
    })
  } catch (e) {
    console.error('拖拽数据解析失败:', e)
  }
}

// 检查是否会造成循环引用的工具函数
const wouldCreateCircularReference = (sourceId: number, targetId: number): boolean => {
  // 简单的循环检测：如果源节点是目标节点的祖先，则会造成循环
  const isAncestor = (ancestorId: number, descendantId: number): boolean => {
    if (ancestorId === descendantId) return true
    
    // 这里需要遍历整个文档树来检查祖先关系
    // 由于我们在组件中没有完整的文档树，这个检查需要在父组件中进行
    // 暂时返回false，在父组件中进行更完整的检查
    return false
  }
  
  return isAncestor(sourceId, targetId)
}
</script>

<style scoped>
.tree-node {
  user-select: none;
}

.node-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.5rem 1rem;
  cursor: pointer;
  transition: all 0.2s;
  border-left: 3px solid transparent;
}

.node-content:hover {
  background: #f0f9ff;
}

.node-content.selected {
  background: #e6f7ff;
  border-left-color: #42b883;
  color: #42b883;
  font-weight: 500;
}

.node-left {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex: 1;
  min-width: 0;
}

.expand-btn {
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  width: 16px;
  height: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.7rem;
  color: #666;
  transition: transform 0.2s;
  flex-shrink: 0;
}

.expand-btn.expanded {
  transform: rotate(90deg);
}

.expand-btn:hover {
  color: #42b883;
}

.expand-placeholder {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

.node-title {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.9rem;
}

.node-actions {
  display: flex;
  gap: 0.25rem;
  opacity: 0;
  transition: opacity 0.2s;
}

.node-content:hover .node-actions {
  opacity: 1;
}

.action-btn {
  background: none;
  border: none;
  cursor: pointer;
  padding: 0.2rem;
  border-radius: 3px;
  font-size: 0.7rem;
  transition: all 0.2s;
}

.action-btn:hover {
  background: rgba(66, 184, 131, 0.1);
}

.edit-btn:hover {
  background: rgba(116, 185, 255, 0.2);
}

.delete-btn:hover {
  background: rgba(253, 121, 168, 0.2);
}

.children {
  margin-left: 1rem;
  border-left: 1px solid #e1e1e1;
}

.children .tree-node {
  position: relative;
}

.children .tree-node::before {
  content: '';
  position: absolute;
  left: -1px;
  top: 0;
  width: 12px;
  height: 100%;
  border-bottom: 1px solid #e1e1e1;
  border-left: 1px solid #e1e1e1;
}

.children .tree-node:last-child::before {
  border-left: 1px solid #e1e1e1;
  border-bottom: 1px solid #e1e1e1;
  height: calc(0.5rem + 0.5rem + 1px);
}

/* 拖拽相关样式 */
.tree-node {
  position: relative;
}

.node-content[draggable="true"] {
  cursor: grab;
}

.node-content[draggable="true"]:active {
  cursor: grabbing;
}

.node-content.dragging {
  opacity: 0.5;
  transform: scale(0.95);
  background: rgba(66, 184, 131, 0.1);
  border-left-color: #42b883;
}

.node-content.drag-over {
  background: rgba(66, 184, 131, 0.15);
  border-left-color: #42b883;
  transform: scale(1.02);
}

/* 拖拽时的插入位置指示器 */
.node-content.drag-over::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  height: 2px;
  background: #42b883;
  border-radius: 1px;
  z-index: 10;
}

.node-content.drag-over[data-drop-position="before"]::before {
  top: -1px;
}

.node-content.drag-over[data-drop-position="after"]::before {
  bottom: -1px;
}

.node-content.drag-over[data-drop-position="inside"]::before {
  display: none;
}

.node-content.drag-over[data-drop-position="inside"] {
  background: rgba(66, 184, 131, 0.2);
  box-shadow: inset 0 0 0 2px rgba(66, 184, 131, 0.5);
}

/* 深色主题下的拖拽样式 */
.dark .node-content.dragging {
  background: rgba(66, 184, 131, 0.15);
}

.dark .node-content.drag-over {
  background: rgba(66, 184, 131, 0.2);
}

.dark .node-content.drag-over[data-drop-position="inside"] {
  background: rgba(66, 184, 131, 0.25);
  box-shadow: inset 0 0 0 2px rgba(66, 184, 131, 0.6);
}

/* 拖拽时禁用文本选择 */
.tree-node.drag-active {
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}

/* 拖拽动画 */
.node-content {
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}

.node-content.dragging {
  transition: none;
}
</style>